home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
MNetsrc.hqx
/
Mac TCP_IP Source v.33
/
mac_tools.c
< prev
next >
Wrap
Text File
|
1989-04-06
|
38KB
|
1,353 lines
#include "mac_tools.h" /* define compiler in here */
#include <MemoryMgr.h>
#include <Quickdraw.h>
#include <EventMgr.h>
#include <ResourceMgr.h>
#include <TextEdit.h>
#include <DialogMgr.h>
#include <strings.h>
#include <stdio.h>
#include <PackageMgr.h>
#include <ToolboxUtil.h>
#include <StdFilePkg.h>
#include <pascal.h>
#include "global.h"
#define ZZ
#define TRUE (-1) /* local definitions */
#define FALSE 0
#define maxsruns 50 /* procedure table size */
#define MESSN 30 /* array size for message dialog items */
#define QUESN 40 /* array size for prompt dialog items */
#define ROM85 0x28E /* new rom stuff */
#define NEWROM 0x7FFF
#define inzoomout 8
#define inzoomin 7
#define zoomproc 8
typedef struct { /* structure for an Item */
char itemname[40];
int itemno; /* Item number within menu */
int menuId; /* menu id */
MenuHandle menuhand; /* Item's menu's Handle */
ProcPtr menurun; /* procedure to run */
Ptr next; /* pointer to the next Item */
} itemdatum;
typedef struct { /* structure for a menu */
char menuname[20]; /* to allow reference by name */
int menuId; /* menu id */
MenuHandle menuhand; /* menu Handle to reference menu*/
itemdatum **itemlist; /* pointer to the list of items */
Ptr next; /* pointer to the next menu */
} menudatum;
typedef struct { /* structure for a window */
char windname[80]; /* window's name and reference */
WindowPtr wptr; /* window's pointer reference */
ProcPtr wact; /* the activate procedure */
ProcPtr wdeact; /* the deactivate procedure */
ProcPtr wupdate; /* the update procedure */
ProcPtr wcontent; /* the content procedure */
Ptr next; /* pointer to the next window */
} winddatum;
pascal Boolean *TrackBox() = 0xA83B;
pascal void *ZoomWindow() = 0xA83A;
WindowPtr windowpoint();
extern struct SysEnvRec *sysenvn;
/* Local variables */
static menudatum **simplemenus; /* Handle to menu data */
static char accname[80]; /* desk accessory name to open */
static Rect dragrect, sizerect; /* limits for moving windows */
static Rect swholescreen;
static winddatum **simplewinds; /* Handle to window data */
static int firstwind; /* if no windows have been made */
static ProcPtr simpleruns[maxsruns]; /* list of procedures to run */
static WindowPtr debugw; /* window pointer for debugging */
static int snewrom;
static int getlinecaps = FALSE;
static int MFenable = 0;
static long MFticks = 0L;
/************************************************************************/
/* GLOBAL USER MODIFIABLE VARIABLES */
/* These are variables that you can declare extern so that you can use */
/* them to change the SimpleTools defaults */
/************************************************************************/
/* wprocid = type of window to Create on next window() call */
int wprocid = documentProc;
/* dogoaway = is the next created window to have a go-away box */
int dogoaway = TRUE;
/* keydownproc = the procedure to be called when keyDown is detected */
/* autokeyproc = the procedure to be called when autoKey is detected */
/* BOTH OF THESE ARE PASSED THE EVENTRECORD SO THE KEY CAN BE FOUND */
ProcPtr keydownproc,
autokeyproc;
/* applestring = a string containing the Apple for menu reference */
char applestring[2]
= {'\024', '\0'};
/* windmenu = does the next window created get a choice under the
window menu (so a closed window can be brought back) */
int windmenu = TRUE;
/* sizeredraw = is the window's content area erased and made
updateable upon being resized */
int sizeredraw = FALSE;
/******************************************************************/
/* Dialog lists. These were calculated by using the new resource */
/* editor to make a template for a dialog and then using fedit to */
/* list the hex listing of the Item list for the dialog. */
/******************************************************************/
int messd[MESSN] = {2,0,0,0x38,0xf1,0x4c,0x12d,0x402,0x4f4b,0,0,5,5,
0x36,0x12d,0x800,0,0,0x38,0xac,0x4c,0xe8,0x406,
0x4361,0x6e63,0x656c};
int quesd[QUESN] = {3,0,0,0x21,0xf0,0x35,0x12c,0x402,0x4f4b,0,0,8,8,
0x28,0xe8,0x800,0,0,0x2b,8,0x4b,0xe8,0x1000,0,0,
8,0xf0,0x1c,0x12c,0x406,0x4361,0x6e63,0x656c};
/* Local procedure */
static
stnop() /* a no op procedure for defaults */
{
}
#define ptoc PtoCstr
#define ctop CtoPstr
/* Given a menu name, find our data structure for it. Return a Handle
to this structure. This is a local procedure for SimpleTools use.
*/
/* local procedure */
static
menudatum **getourmenuhandle (name)
char *name; /* name of menu bar menu */
{
menudatum **here, **temp; /* hand to menu structure*/
here = simplemenus;
/* find the menu name or the end of out menu list */
HLock (here);
while (strcmp(name,(**here).menuname) && (**here).next ) {
temp = here;
here = (menudatum **)(**here).next;
HUnlock (temp);
HLock (here);
}
/* see if we found it or just the end of the list */
if (!strcmp(name,(**here).menuname)) {
HUnlock (here);
return (here);
} else {
HUnlock (here);
return ((menudatum **)0L);
}
}
/* This takes a Handle to our personal Item record and either a
procedure name or a modifier code. If it got a procedure name,
it sets it to the Item's procedure to run when the Item is chosen.
If it got a modifier code, it changes the state of the menu's Item
to checked, unchecked, enabled, or disabled. It especially keeps
track of the standard Edit menu items so we can restore them after
a desk accessory is finished.
*/
/* Local procedure */
static
setitems ( items, routine) /* set a menu Item's routine or display */
itemdatum **items; /* if items is neg, then whole menu */
ProcPtr routine;
{
int inumber;
MenuHandle mhand;
/* check to see if a procedure pointer was given to us */
if ( (((long)items)>0L) && (routine > (ProcPtr)0x1000L)) {
/* good procedure value */
(**items).menurun = routine;
return;
}
/* Calculate which Item number we are going to modify */
if ( (long)items < 0L) { /* the whole menu */
mhand = (MenuHandle) (0L - (long)items);
inumber = 0;
} else { /* just one Item */
mhand = (**items).menuhand;
inumber = (**items).itemno;
}
/* If a NULL procedure pointer, then set to a no_op routine */
if ( (inumber > 0) && ((**items).menurun == (ProcPtr)0L) )
(**items).menurun = stnop;
/* Now change the state of a menu Item */
switch ((int)routine) {
case itemdisable:
DisableItem(mhand,inumber); break;
case itemenable:
EnableItem(mhand, inumber); break;
case itemcheck:
CheckItem(mhand, inumber, TRUE); break;
case itemuncheck:
CheckItem(mhand, inumber, FALSE); break;
}
if (inumber == 0) DrawMenuBar(); /* if main menu was changed */
}
/* This routine is called by the simpletools() initial routine. It gets
the pointer list of menus started, loads the desk accessories into
the Apple menu, and loads up some standard menu entries. The reason
menu File has a New entry, and none others, is because as this code
currently stands, a menu must have at least one Item. And since we
want File before Edit, I had to make an entry. The most commonly used
Item under File is Quit. But we like quit to be at the end of the list.
So, since New is usually always first when it is used, that the one
chosen to start File.
*/
/* Local procedure */
static
initsmenus(about) /* init simpletools' menus */
char *about;
{
itemdatum **items;
simplemenus = (menudatum **) NewHandle ( (long)sizeof(menudatum));
HLock (simplemenus);
strcpy ( (**simplemenus).menuname, applestring);
(**simplemenus).menuId = 1;
(**simplemenus).next = (Ptr) 0L;
ctop ((**simplemenus).menuname);
(**simplemenus).menuhand = NewMenu (1, (**simplemenus).menuname);
ptoc ((**simplemenus).menuname);
HUnlock ((**simplemenus).menuhand);
(**simplemenus).itemlist = (itemdatum **)NewHandle (
(long)sizeof(itemdatum));
items = (itemdatum **) (**simplemenus).itemlist;
HLock (items);
strcpy ((**items).itemname, about);
(**items).itemno = 1;
(**items).menuId = 1;
(**items).menuhand = (**simplemenus).menuhand;
(**items).menurun = stnop;
(**items).next = 0L;
HUnlock (items);
ctop (about);
AppendMenu ((**simplemenus).menuhand, about);
ptoc (about);
menu (applestring, about, (ProcPtr)itemenable);
menu (applestring, "Help" , (ProcPtr)itemenable);
menu (applestring, "-", (ProcPtr) itemdisable);
AddResMenu ((**simplemenus).menuhand, 'DRVR');
InsertMenu ((**simplemenus).menuhand, 0);
HUnlock (simplemenus);
menu ("File", "New", (ProcPtr)itemdisable);
menu ("Edit", "Undo", (ProcPtr)stnop);
menu ("Edit", "-", (ProcPtr)itemdisable);
menu ("Edit", "Cut/X", (ProcPtr)stnop);
menu ("Edit", "Copy/C", (ProcPtr)stnop);
menu ("Edit", "Paste/V", (ProcPtr)stnop);
menu ("Edit", "Clear", (ProcPtr)stnop);
}
/* Local procedure */
static
gottrans ()
{
char prog[80];
char *argv[3];
if (getfile("APPL",prog)) {
argv[1] = NULL;
execv(prog,argv);
}
}
/* Local procedure */
static
gotquit ()
{
exit(0);
}
/* This routine is for the Windows menu Item. The Windows menu is
set up when new windows are added. It is used to bring forward and
bring into view windows that may be under other windows or have been
sent hiding by a click on their close box.
*/
/* Local procedure */
static
showawindow(name) /* show the named window */
char *name;
{
WindowPtr foo;
foo = windowpoint(name); /* get its window pointer */
if ( foo ) {
ShowWindow(foo); /* show it on the screen */
SetPort (foo); /* set further output to it */
if ( foo != FrontWindow()) /* if it isn't active, */
SelectWindow (foo); /* activate it */
}
}
/* Local procedure */
static
winddatum **wdatum(windpt) /* return Handle to window data */
WindowPtr windpt;
{
winddatum **wind, **temp;
if (firstwind) return ((winddatum **) 0L);
wind = simplewinds;
HLock (wind);
while ( ((**wind).wptr != windpt) && (**wind).next) {
temp = wind;
wind = (winddatum **) (**wind).next;
HUnlock (temp);
HLock (wind);
}
if ( (**wind).wptr == windpt) {
HUnlock (wind);
return (wind);
} else {
HUnlock (wind);
return ((winddatum **) 0L); /* zero if not found */
}
}
/* Local procedure */
static
runruns(event) /* run all the installed run procedures */
EventRecord *event; /* returns number of routines run */
{
int i=0;
WindowPtr saveport;
GetPort (&saveport);
while ( simpleruns[i] )
(*(simpleruns[i++])) (event);
SetPort (saveport);
return(i);
}
/* Local procedure */
static
stdialog( question, answer, type) /* a general dialog displayer */
char *question;
char *answer;
int type; /* type: 1=prompt, 2=message */
{
DialogPtr dialog; /* dialog reference */
Handle Item, items; /* handles for the dialog items */
Rect screen, box; /* rectangles for dialog/items */
int dtype, hit, canc; /* Item type and which was hit */
char tempanswer[256]; /* address where answer is */
items = NewHandle (512L);/* get memory for items list */
HLock (items); /* lock it down */
if (type == 1)
BlockMove (quesd, *items, (long) QUESN * 2L);
else
BlockMove (messd, *items, (long) MESSN * 2L);
SetRect (&screen, 103, 50, 409, 137);
dialog = NewDialog (0L, &screen, "", 0, dBoxProc, -1L, 0, 0L, items);
GetDItem (dialog, 2, &dtype, &Item, &box);
ctop (question);
SetIText (Item, question); /* set Item#2 text */
ptoc (question);
if (type == 1) { /* set default answer */
GetDItem (dialog, 3, &dtype, &Item, &box);
ptoc (answer);
SetIText (Item, answer);
ctop (answer);
canc = 4;
} else
canc = 3;
ShowWindow (dialog); /* display the dialog */
do {
ModalDialog (0L, &hit); /* process the dialog */
} while ( (hit != 1) & (hit != canc) );
if (type == 1) {
GetDItem (dialog, 3, &dtype, &Item, &box);
HLock (Item);
GetIText (Item, tempanswer); /* get Item#3 text */
ptoc (tempanswer);
strcpy (answer, tempanswer); /* make a copy of it */
HUnlock (Item);
}
HUnlock(items); /* unlock items memory */
HPurge(items); /* purge it */
DisposDialog (dialog); /* get rid of dialog */
return ( hit==1 ); /* return true if ok */
}
/* Local procedures */
static
docommand (which, thisevent)
long which;
EventRecord *thisevent;
{
int themenu, theitem;
long size;
char *cpoint;
GrafPtr tempport;
menudatum **here, **temp;
itemdatum **items, **tempitems;
char **myreshandle;
Handle myhandle;
themenu = HiWord (which);
theitem = LoWord (which);
if ((themenu == 1) && (theitem >= 3)) {
/* start up a desk accessory */
HLock (simplemenus);
GetItem ((**simplemenus).menuhand, theitem, accname);
SetResLoad (FALSE);
myreshandle = GetNamedResource ('DRVR', accname);
SetResLoad (TRUE);
size = SizeResource (myreshandle);
myhandle = NewHandle ( size + 3072L);
if (myhandle == 0L)
message ("Not enough memory to do that.");
else {
DisposHandle (myhandle);
GetPort (&tempport);
OpenDeskAcc(accname);
SetPort (tempport);
}
HUnlock (simplemenus);
return;
}
if (themenu ==3) {
/* do any system edits */
if (SystemEdit(theitem -1)) return;
}
/* now we run an installed menu procedure */
here = simplemenus;
HLock (here);
/* find out menu structure given the menu id */
while ( ((**here).menuId != themenu) && (**here).next) {
temp = here;
here = (menudatum **)(**here).next;
HUnlock (temp);
HLock (here);
}
if ((**here).menuId == themenu) {
/* now find the Item structure */
items = (**here).itemlist;
HUnlock (here);
HLock (items);
while ( ((**items).itemno != theitem) && (**items).next) {
tempitems = items;
items = (itemdatum **)(**items).next;
HUnlock (tempitems);
HLock (items);
}
/* prepare to give the Item name to the procedure */
cpoint = (**items).itemname;
if ((**items).itemno == theitem)
/* if we found the Item, call its procedure */
(*((**items).menurun))(cpoint,thisevent) ;
HUnlock (items);
}
}
/* Local procedure */
static
domousedown(thisevent) /* respond to mouse down events */
EventRecord *thisevent; /* passed the event record */
{
WindowPtr whichwindow;
int code, x, y;
char *cpoint;
menudatum **omhand;
winddatum **thewdatum;
long newplace;
Point temp;
GrafPtr saveport;
code = FindWindow(ZZ(thisevent->where), &whichwindow);
switch (code) {
case inMenuBar:
docommand(MenuSelect(ZZ(thisevent->where)),thisevent);
break;
case inSysWindow:
SystemClick(thisevent, whichwindow); break;
case inDrag:
DragWindow(whichwindow, ZZ(thisevent->where),
&dragrect); break;
case inGrow:
newplace= GrowWindow(whichwindow, ZZ(thisevent->where),
&sizerect);
SizeWindow(whichwindow, LoWord(newplace),
HiWord(newplace), TRUE);
if (sizeredraw) {
GetPort (&saveport);
SetPort (whichwindow);
EraseRect (&swholescreen);
InvalRect (&swholescreen);
SetPort (saveport);
}
break;
case inGoAway:
if ( TrackGoAway(whichwindow, ZZ(thisevent->where))) {
HideWindow (whichwindow);
}
break;
case inzoomout:
case inzoomin:
if ( TrackBox(whichwindow, ZZ(thisevent->where), code)) {
ZoomWindow (whichwindow, code, 0);
GetPort (&saveport);
SetPort (whichwindow);
EraseRect (&swholescreen);
InvalRect (&swholescreen);
SetPort (saveport);
}
break;
case inContent:
/* make the window active if it isn't yet */
if (whichwindow != FrontWindow()) {
SelectWindow(whichwindow);
}
/* find our window data */
thewdatum = wdatum (whichwindow);
if (thewdatum) {
/* convert the Point of click to the window's
own coordinates since this will be always
more useful than the global coordintates */
temp = thisevent->where;
SetPort (whichwindow);
GlobalToLocal (&temp);
x = temp.h;
y = temp.v;
/* call the window's in content routine */
HLock (thewdatum);
(*((**thewdatum).wcontent))(x, y, whichwindow,
thisevent);
HUnlock (thewdatum);
}
break;
}
}
/* Local procedure */
/* Determine if MultiFinder is running by checking for the existence of the
WaitNextEvent() trap */
static int
MFIsRunning()
{ /* $8F is for _MFDispatch, $9F is the unimplemented trap */
return (GetTrapAddress(0x8FL) != GetTrapAddress(0x9FL));
}
/************************************************************************/
/* GLOBAL ROUTINES INTENDED TO BE USER CALLABLE PROCEDURES */
/* THE FOLLOWING PROCEDURES HAVE BEEN WRITTEN FOR THE USER'S */
/* APPLICATION TO CALL. */
/* */
/************************************************************************/
havenewrom () /* returns true if new roms installed */
{
return ((*((int *)ROM85)) == NEWROM);
}
/* Menu is usually called like:
menu ("File", "Print...", got_print)
where the first argument is the name appearing on the menubar. The
2nd argument is the name appearing when the menu is pulled down. The
3rd argument is USUALLY the routine to be called when the user
selects this particular menu. Non-existant menus are created following
the last. The menu ordering may never be changed once created.
Existint menus have their "routine-to-be-executed" assignment changed
to the new routine. If the long values 0L, 1L, 2L, or 3L are passed
instead of a procedure, the menu characteristic is set as specified
by the constants itemdisable, itemenable, itemcheck, itemuncheck. For
example:
menu ("File", "Print...", itemdisable)
PROCEDURES ASSIGNED TO MENUS ARE CALLED WITH TWO ARGUMENTS. YOU
DO NOT NEED TO DECLARE THESE IN YOUR PROCEDURE IF YOU DO NOT USE
THEM. FOR EXAMPLE, GOT_PRINT MAY BE DECLARED AS:
got_print()
char *itemname;
EventRecord *current_event;
{
...
}
Itemname is a char* pointing to the Item name. This allows the same
menu procedure to be used for multiple menu/Item pairs. Maybe your
Size menu just as items 9 Point, 10 Point, 12 Point, etc. This way
you can specify the same procedure for each and determine what to do
by looking at itemname.
Current_event is a pointer to the current EventRecord that detected
the menu selection. You may look at this as needed.
*/
menu (name, Item, routine) /* install or change a menu */
char *name; /* the menu name */
char *Item; /* the Item name */
ProcPtr routine; /* a procedure or modifier */
{
menudatum **here,**temp; /* a roving Handle to our data */
menudatum **ourmhandle; /* another Handle to our data */
itemdatum **items,**tempitems; /* a Handle to the Item */
int lastid, lastitem;
/* get the Handle to menu named 'name' */
if ((ourmhandle = getourmenuhandle (name)) == 0L) {
/* make a new menu entry by finding the end of the list */
here = simplemenus;
HLock (here);
while ((**here).next) {
temp = here;
here = (menudatum **)(**here).next;
HUnlock (temp);
HLock (here);
}
/* make a structure for our new entry */
lastid = (**here).menuId;
(**here).next = (Ptr)NewHandle ( (long)sizeof(menudatum));
temp = here;
here = (menudatum **)(**here).next;
HUnlock (temp);
HLock (here);
strcpy ( (**here).menuname, name);
(**here).menuId = ++lastid;
(**here).next = (Ptr) 0L;
/* make a new Item structure */
(**here).itemlist = (itemdatum **)NewHandle (
(long)sizeof(itemdatum));
/* make a new menu entry for the Macintosh */
ctop (name);
(**here).menuhand = NewMenu (lastid, name);
ptoc (name);
items = (**here).itemlist;
HLock (items);
strcpy ((**items).itemname, Item);
(**items).itemno = 1;
(**items).menuId = lastid;
(**items).menuhand = (**here).menuhand;
(**items).menurun = (ProcPtr) 0L;
(**items).next = 0L;
HUnlock (items);
/* install and display the menu */
ctop (Item);
AppendMenu ((**here).menuhand, Item);
ptoc (Item);
InsertMenu ((**here).menuhand,0);
HUnlock (here);
setitems (items, routine);
DrawMenuBar();
return(TRUE);
}
else {
HLock (ourmhandle);
if (strlen(Item) == 0) {
/* then adjust main menu */
setitems( 0L - (long) ((**ourmhandle).menuhand), routine);
return(FALSE);
}
/* see if Item is in list */
items = (**ourmhandle).itemlist;
HLock (items);
while ( strcmp(Item,(**items).itemname) && (**items).next) {
tempitems = items;
items = (itemdatum **)(**items).next;
HUnlock (tempitems);
HLock (items);
}
if (strcmp(Item,(**items).itemname) ==0) {
setitems( items, routine);
return(FALSE);
}
else {
/* make new Item entry */
lastitem = (**items).itemno;
(**items).next =(Ptr)NewHandle((long)sizeof(itemdatum));
tempitems = items;
items = (itemdatum **)(**items).next;
HUnlock (tempitems);
HLock (items);
strcpy ((**items).itemname, Item);
(**items).itemno = ++lastitem;
(**items).menuId = (**ourmhandle).menuId;
(**items).menuhand = (**ourmhandle).menuhand;
(**items).menurun = (ProcPtr) 0L;
(**items).next = 0L;
HUnlock (items);
/* and install the Item in the menu bar */
ctop (Item);
AppendMenu ((**ourmhandle).menuhand,Item);
ptoc (Item);
HUnlock (ourmhandle);
setitems (items, routine);
return(TRUE);
}
}
}
/* Given a menu name, return the real menu Handle as used by most
of the Macintosh toolbox menu manager routines.
*/
MenuHandle mhand (name) /* find MenuHandle */
char *name; /* given name of menu */
{
menudatum **menu;
MenuHandle temp; /* a Handle to our data */
menu = getourmenuhandle(name);
if ( menu ) {
HLock (menu);
temp = (**menu).menuhand;
HUnlock (menu);
return ( temp ); /* return menu Handle */
} else
return ( (MenuHandle) 0 );
}
/* Call this routine if you want these SimpleTools defined quiting */
/* procedures. You may just install your own instead. The time to */
/* call this is after you have installed all your other "File" items. */
/* By calling this last, you will place Transfer and Quit on the end */
/* of the menu list. */
mac_toolquits ()
{
menu ("File", "-", itemdisable);
menu ("File", "Transfer.../T", gottrans);
menu ("File", "Quit/Q", gotquit);
}
/* Given a window's name, return its window pointer so that other
Macintosh Window Manager routines can be called for that window. */
WindowPtr windowpoint(name) /* get window pointer */
char *name; /* given window's name */
{
winddatum **wind, **tempwind; /* Handle to our window data */
WindowPtr temp;
if (firstwind) return ((WindowPtr)0);
wind = simplewinds; /* look for the named window */
HLock (wind);
while ( strcmp ((**wind).windname, name) && (**wind).next) {
tempwind = wind;
wind = (winddatum **) (**wind).next;
HUnlock (tempwind);
HLock (wind);
}
if ( strcmp ((**wind).windname, name) ==0) {
temp = (**wind).wptr;
HUnlock (wind);
return ( temp ); /* return pointer */
} else {
HUnlock (wind);
return ( (WindowPtr) 0);/* or zero if it wasn't found */
}
}
/* This routine installs a new window onto the screen. It also gives
that window an Item in the Window menu. This routine is also used
to modify a window's associated routines. The x,y positions are the
top left and bottom right corners of where the window should originally
be placed. The coordinates are never used when this routine is called
to update an already existing window. But the spaces must be filled,
so you can use zeros if you want. Once the window has been displayed in
its original position, the user has complete control of its size and
placement with the mouse.
YOU MUST ASSIGN PROCEDURES TO BE CALLED WHEN SIMPLETOOLS DETECTS THAT
THIS WINDOW IS BECOMMING ACTIVE, DEACTIVATING, NEEDS UPDATING, OR
THE MOUSE HAS BEEN PRESSED IN ITS CONTENT. JUST LIKE THE MENU PROCEDURE,
THESE PROCEDURES ARE PASSED SOME ARGUMENTS. YOU DO NOT HAVE TO
DECLARE THESE IF YOU DON'T WHAT TO USE THEM. IF YOU USE THE ARGUMENTS,
YOU WOULD DECLAR THESE PROCEDURES AS FOLLOWS:
my_activate (windp, event) same as my_update
my_deactivate (windp, event) same as my_update
my_update (windp, event)
WindowPtr windp; the window being acted upon
EventRecord *event; the current event record
{
...
}
my_inContent (x, y, windp, event)
int x, y; mouse position in local coords
WindowPtr windp; like above
EventRecord *event; like above
{
...
}
*/
window(name, xtop, ytop, xbot, ybot, a, d, u, c)
char *name; /* window's name */
int xtop, ytop, xbot, ybot; /* position if this is a new window */
ProcPtr a, d, u, c; /* activate, deactivate, update, and */
{ /* content procedures */
winddatum **wind, **temp;/* Handle to our window data */
winddatum **newentry; /* another Handle */
Rect newplace; /* rectable for the window's placement */
if (a == (ProcPtr) 0)
a = stnop;
if (d == (ProcPtr) 0)
d = stnop;
if (u == (ProcPtr) 0)
u = stnop;
if (c == (ProcPtr) 0)
c = stnop;
if ( !firstwind ) {
/* see if window is in the list */
wind = simplewinds;
HLock (wind);
while ( strcmp ((**wind).windname, name) && (**wind).next) {
temp = wind;
wind = (winddatum **) (**wind).next;
HUnlock (temp);
HLock (wind);
}
if ( strcmp ((**wind).windname, name) ==0) {
/* reset the found window's parameters */
(**wind).wact = (ProcPtr) a;
(**wind).wdeact = (ProcPtr) d;
(**wind).wupdate = (ProcPtr) u;
(**wind).wcontent = (ProcPtr) c;
SetPort ( (**wind).wptr);
HUnlock (wind);
return(FALSE);
}
}
/* make a new window entry */
newentry = (winddatum **)NewHandle ( (long) sizeof (winddatum));
if (firstwind)
simplewinds = newentry;
else
(**wind).next = (Ptr) newentry;
firstwind = 0;
HUnlock (wind);
HLock (newentry);
strcpy ((**newentry).windname, name);
SetRect (&newplace, xtop, ytop, xbot, ybot);
if (EmptyRect (&newplace))
SetRect (&newplace, 10, 42, 500, 330);
ctop (name);
(**newentry).wptr = NewWindow (0L, &newplace, name, -1,
wprocid, -1L, dogoaway, newentry);
ptoc (name);
(**newentry).wact = (ProcPtr) a;
(**newentry).wdeact = (ProcPtr) d;
(**newentry).wupdate = (ProcPtr) u;
(**newentry).wcontent = (ProcPtr) c;
(**newentry).next = (Ptr) 0;
if (windmenu)
menu ("Windows", name, showawindow);
SetPort ( (**newentry).wptr);
HUnlock (newentry);
return(TRUE);
}
withwindow(name) /* set output to window by name */
char *name; /* give it the window's name */
{ /* returns if window exists */
winddatum **wind, **temp;
wind = simplewinds;
if (firstwind) return(FALSE); /* search for the window's name */
HLock (wind);
while ( strcmp ((**wind).windname, name) && (**wind).next) {
temp = wind;
wind = (winddatum **) (**wind).next;
HUnlock (temp);
HLock (wind);
}
if ( strcmp ((**wind).windname, name) ==0) {
SetPort ( (**wind).wptr); /* set output to it */
HUnlock (wind);
return(TRUE);
} else {
HUnlock (wind);
return(FALSE);
}
}
/* This run procedure is used to install routines to be occasionally
run. The routine will be run once for each call to simpleevents()
which is done repeatedly by runsimpletools().
EACH ROUTINE INSERTED INTO THE RUN LIST IS RUN MULTIPLE TIMES UNTIL
IT IS REMOVED BY CALLING STOP. THE ROUTINE IS CALLED WITH A SINGLE
ARGUMENT, A POINTER TO THE EVENT JUST RETURNED BY GETNEXTEVENT() AND
BEFORE SIMPLETOOLS PROCESSES IT.
*/
run(routine) /* install a run procedure */
ProcPtr routine; /* give it the procedure */
{ /* return TRUE if successful */
int i;
i = 0; /* add it to the end of the list */
while ( simpleruns[i] != (ProcPtr) 0L) i++;
if (i < maxsruns) {
simpleruns[i] = routine;
simpleruns[i+1] = (ProcPtr) 0L;
return(TRUE);
} else
return(FALSE);
}
/* This routine removes a procedure from the list of run procedures */
stop(routine) /* stop a procedure from running*/
ProcPtr routine; /* give the procedure */
{ /* return TRUE if successful */
int i = 0;
while ( (simpleruns[i] != routine) && simpleruns[i]) i++;
if (simpleruns[i]) {
while ( simpleruns[i] != (ProcPtr)0 ) {
simpleruns[i] = simpleruns[i+1];
i++;
}
return(TRUE);
} else {
return(FALSE);
}
}
home () /* text-based home of the pen with
the window being erased. */
{
GrafPtr port;
GetPort (&port);
EraseRect (&(port->portRect));
stgotoxy (1, 1);
}
stgotoxy (x, y) /* goto text position x, y */
int x, y;
{
Point pt;
int newx, newy;
FontInfo font;
GetFontInfo (&font);
GetPen (&pt);
if (x < 0)
newx = pt.h;
else
newx = font.widMax * (x);
if (y < 0)
newy = pt.v;
else
newy = (font.ascent + font.descent + font.leading) * (y+1);
MoveTo (newx, newy);
}
/* The getline procedure is to be called when you want to simply get a Line
of text from the user at the current pen position on the screen. You
will probably preceed this with a call to stgotoxy(x,y). You would call
it like:
getline ("Erik", name);
where name is a character array. This works MUCH better than scanf()
or gets() since it uses the Macintosh TextEdit routines to allow the
user to edit the Line being input.
Getline is very "modal" and no other events are handled while the
user is expected to enter the Line. Getline returns ONLY when the
user presses <RETURN>.
Routines scheduled to run by the run() routine are called. Make sure
your run routines don't strip all <RETURNS> from the event record
they get or getline will never stop.
*/
getline (dfault, destination) /* using TE, get a Line */
char *dfault, *destination; /* default string, dest */
{
TEHandle hte;
Rect destRect;
Point pen,pt;
FontInfo FInfo;
int done, mask, code, in_already, nextcap;
GrafPtr port, window;
EventRecord event;
char key;
CursHandle c;
GetPort (&port); /* Calculate Rect for TE */
if (port != FrontWindow()) SelectWindow (port);
GetPen (&pen);
GetFontInfo (&FInfo);
SetRect (&destRect, pen.h, pen.v - FInfo.ascent,
1000, pen.v + FInfo.descent);
EraseRect (&destRect);
hte = TENew (&destRect, &destRect);
TESetText (dfault, (long)strlen(dfault), hte);
TEActivate (hte);
TEUpdate (&destRect, hte);
mask = mDownMask + keyDownMask + autoKeyMask + mUpMask;
done = FALSE;
c = GetCursor (iBeamCursor);
in_already = FALSE;
nextcap = getlinecaps;
do { /* "modal" loop until <cr> */
SystemTask ();
TEIdle (hte);
GetNextEvent (mask, &event);
runruns (&event);
GetMouse (&pt); /* use I beam in TE */
if (PtInRect (ZZ(pt), &destRect)) {
if ( ! in_already ) {
SetCursor (*c);
in_already = TRUE;
}
} else {
if ( in_already ) {
InitCursor ();
in_already = FALSE;
}
}
switch (event.what) {
case mouseDown:
code = FindWindow (ZZ(event.where),&window);
if ((code == inContent) && (window == port)) {
GlobalToLocal (&event.where);
if (PtInRect(ZZ(event.where),&destRect))
TEClick (ZZ(event.where), 0, hte);
else SysBeep (1);
} else SysBeep (20);
break;
case keyDown:
case autoKey:
key = (char) (event.message & 0xFFL);
if (nextcap && (key >= 'a') && (key <= 'z'))
key -= ' ';
nextcap = FALSE;
if (key == ' ') nextcap = getlinecaps;
if (key != '\r') TEKey (key, hte);
else done = TRUE;
break;
}
} while (!done);
TEDeactivate (hte);
strncpy (destination, *TEGetText(hte), (*hte)->teLength);
destination[(*hte)->teLength] = 0;
TEDispose (hte);
InitCursor ();
}
/* Use prompt when you want a tiny window to pop up to ask the user
a question. The question is drawn and a TextEdit box is provided
to get the answer. Whatever the user leaves in the answer box
is returned in answer. Two buttons are also displayed: OK and
CANCEL. Prompt returns TRUE or FALSE depending on which Button was
pressed.
*/
prompter ( question, answer) /* dialog box question/answer */
char *question;
char *answer;
{
return (stdialog (question, answer, 1));
}
/* Message is just like prompt except no answer box is displayed. An
OK and CANCEL Button works just like prompt.
*/
message ( message ) /* dialog box message */
char *message;
{
return (stdialog (message, message, 2));
}
/* This routine is a simpler whay to call the toolbox SFGetFile()
routine. Simple call this like:
getfile ("TEXT", filename)
where filename is a character array. Replace TEXT with whatever
file type you desire. The file manager's working directory is set
correctly so that a subsequent open() call with filename will work.
*/
getfile (ftype, reply)
char ftype[];
char reply[];
{
Point where;
SFReply frommac;
where.h = 75; where.v = 50;
if (strlen(ftype) != 4)
SFGetFile (ZZ(where), NULL, NULL, -1, NULL, NULL, &frommac);
else
SFGetFile (ZZ(where), NULL, NULL, 1, ftype, 0L, &frommac);
if (frommac.good) {
SetVol ("", frommac.vRefNum);
strcpy (reply, frommac.fName);
return (TRUE);
}
else return (FALSE);
}
/* This is like getfile, but may get a new file name from the user.
Origname is the default you want to present to the user.
*/
putfile (origname,reply)
char *origname;
SFReply *reply;
{
Point where;
SFReply frommac;
where.h = 75; where.v = 50;
SFPutFile (ZZ(where), "", origname, 0L, &frommac);
if (frommac.good) {
SetVol ("", frommac.vRefNum);
strcpy (reply, frommac.fName);
return (TRUE);
}
return (FALSE);
}
/* This routine initializes SimpleTools and MUST be called before */
/* most of the other SimpleTools routines are called. */
/* The passed about string is the menu Item name to appear just under */
/* the Apple menu. This will be disabled and can be enabled using */
/* a menu() call. This routine also initializes the Macintosh */
/* for application execution and desk accessory processing. */
mac_tools(about) /* to be called at the beginning of program */
char *about;
{
InitGraf (&thePort); /* initialize the screen */
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
InitCursor(); /* make the arrow Cursor */
FlushEvents (everyEvent,0); /* ignore left over events */
snewrom = havenewrom();
wprocid = documentProc;
if (snewrom) wprocid = zoomproc;
SetRect ( &sizerect, 20, 50, 250, 330);
simpleruns[0] = (ProcPtr) 0; /* empty the run list */
/* These are the bounds we are allowed to size a window or
Move a window to.
*/
swholescreen = dragrect = thePort -> portRect;
InsetRect (&dragrect, 4, 4);
SetRect ( &sizerect, 20, 20, 2048, 700);
firstwind = 1; /* empty window table */
keydownproc = stnop; /* default key hit procedures */
autokeyproc = stnop;
initsmenus(about); /* install the menus */
if(MFIsRunning())
MFenable = 1; /* Set if MF is on */
}
mac_toolsevents() /* to be called in the main loop */
{
EventRecord newevent;
winddatum **thewdatum;
int c = -1;
long menuEquiv;
HiliteMenu(0);
if(MFenable)
WaitNextEvent(everyEvent, &newevent, MFticks, 0L);
else {
SystemTask(); /* Do the system D.A. etc. stuff */
GetNextEvent(everyEvent, &newevent);
}
runruns(&newevent); /* Do our run procedures */
switch (newevent.what) {
case mouseDown:
if (StdEvent(&newevent))/* Check for stdio only events */
{
return(c); /* Exit if stdio - he's done it */
}
domousedown(&newevent); break;
case keyDown:
if ((newevent.modifiers & cmdKey) &&
(menuEquiv = MenuKey((char)(newevent.message & 0xffL)))){
docommand(menuEquiv);
break;
}
c = newevent.message & charCodeMask;
if ((newevent.modifiers & cmdKey) && /* Map control chars */
(sysenvn->keyBoardType < 4)) /* on non-adb keyboards */
c &= 0x1f; /* make it cntl */
(*(keydownproc))(&newevent);
break;
case autoKey:
if ((newevent.modifiers & cmdKey) &&
(menuEquiv = MenuKey((char)(newevent.message & 0xffL)))){
docommand(menuEquiv);
break;
}
c = newevent.message & charCodeMask;
if ((newevent.modifiers & cmdKey) && /* Map control chars */
(sysenvn->keyBoardType < 4)) /* on non-adb keyboards */
c &= 0x1f; /* make it cntl */
(*(autokeyproc))(&newevent);
break;
case activateEvt:
if (StdEvent(&newevent))/* Check for stdio only events */
{
return(c); /* Exit if stdio - he's done it */
}
thewdatum = wdatum(newevent.message);
if (thewdatum) {
SetPort(newevent.message);
HLock (thewdatum);
if (newevent.modifiers & 1) {
(*((**thewdatum).wact))(newevent.message,
&newevent);
} else {
(*((**thewdatum).wdeact))(newevent.message,
&newevent);
}
HUnlock (thewdatum);
}
break;
case updateEvt:
if (StdEvent(&newevent))/* Check for stdio only events */
{
return(c); /* Exit if stdio - he's done it */
}
thewdatum = wdatum(newevent.message);
if (thewdatum) {
SetPort (newevent.message);
BeginUpdate (newevent.message);
HLock (thewdatum);
(*((**thewdatum).wupdate))(newevent.message,
&newevent);
HUnlock (thewdatum);
EndUpdate (newevent.message);
}
break;
case app4Evt:
if(newevent.message & 0x01)
MFticks = 0; /* Resume event */
else
MFticks = 0; /* Suspend event */
break;
case networkEvt:
case driverEvt:
mac_netevt(newevent.message);
break;
default:
if (StdEvent(&newevent))/* Check for stdio only events */
{
return(c); /* Exit if stdio - he's done it */
}
break;
}
return(c);
}
runsimpletools ()
{
for (;;) mac_toolsevents();
}